/**
 * Project Name:payment
 * File Name:SignUtils.java
 * Package Name:cn.swiftpass.utils.payment.sign
 * Date:2014-6-27下午3:22:33
 */

package com.acooly.module.openapi.client.provider.sinapay.utils;

import com.acooly.core.common.exception.BusinessException;
import com.acooly.core.utils.Strings;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;


/**
 * ClassName:SignUtils
 * Function: 签名用的工具箱
 * Date:     2014-6-27 下午3:22:33
 *
 * @author
 */
@Slf4j
public class SignUtils {

    public final static String RSA_CHIPER = "RSA/ECB/PKCS1Padding";

    /**
     * 编码
     */
    public final static String ENCODE = "UTF-8";

    /**
     * 生成AES加密所需Key的算法 */
    private static final String KEY_ALGORITHM = "AES";

    /**
     * 加解密算法/工作模式/填充方式,Java6.0支持PKCS5Padding填充方式,BouncyCastle支持PKCS7Padding填充方式
     */
    private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";


    /**
     * 组装签名字符串
     * @param jsonMap
     * @return
     */
    public static String getSignStr(TreeMap<String,String> jsonMap){
        StringBuilder sb = new StringBuilder();
        for (Map.Entry entry : jsonMap.entrySet()) {
            sb.append(entry.getValue());
        }
        return sb.toString();
    }

    /**
     * 获取验签字符串
     *
     * @param responseMessage
     * @return
     */
    public static String getVerifySignStr(TreeMap<String,String> responseMessage) {
        StringBuffer signData = new StringBuffer();
        Iterator<Map.Entry<String, String>> iter = responseMessage.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry<String, String> entry = iter.next();

            /** 把sign参数隔过去 */
            if (Strings.equals((String) entry.getKey(), "sign")) {
                continue;
            }
            signData.append(entry.getValue() == null ? "" : entry.getValue());
        }

        return signData.toString();
    }

    /**
     * 函数功能：敏感信息加密,AES算法为AES/CBC/PKCS5Padding
     * 参数：key，16位随机字符串
     * 参数：tobeEncoded，待加密的字符串，如银行卡号，V5版中的数字信封明文
     * 参数：iv,AES加密用到的IV值，V3，V4版本接口为固定值1234567892546398，V5版本接口随商户证书一起提供
     * * */

    public static String aesEncode(String key,String tobeEncoded) {
        try {
            //1.AES加密
            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(ENCODE), KEY_ALGORITHM);
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec seckey = new SecretKeySpec(enCodeFormat,KEY_ALGORITHM);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);// 创建密码器
            cipher.init(Cipher.ENCRYPT_MODE, seckey);// 初始化
            byte[] result = cipher.doFinal(tobeEncoded.getBytes(ENCODE));
            //2.BASE64编码
            return new String(Base64.encode(result));
        }catch (Exception e) {
            log.info("AES加密失败:{}",e.getMessage());
            throw new BusinessException("AES加密失败"+e.getMessage());
        }
    }

    /**
     *敏感信息解密，如银行卡等信息
     *
     **/
    public static String aesDecode(String key,String tobeDecode) throws Exception{
        //BASE64解码
        byte[] base64Bytes=Base64.decode(tobeDecode.getBytes());
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(ENCODE), KEY_ALGORITHM);
        byte[] enCodeFormat = secretKey.getEncoded();
        SecretKeySpec seckey = new SecretKeySpec(enCodeFormat, KEY_ALGORITHM);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);// 创建密码器
        cipher.init(Cipher.DECRYPT_MODE, seckey);// 初始化
        byte[] result = cipher.doFinal(base64Bytes);
        return new String(result,ENCODE);

    }
    /**
     * 函数功能 :RSA非对称加密，用于对16位的AES秘钥进行加密,算法为RSA/ECB/PKCS1Padding
     * 参数：TobeEncryptMsg待加密的字符串，如16位AES秘钥
     * */

    public static String rsaEncode(String TobeEncryptMsg,PublicKey publicKey){
        //获取公钥
        Cipher instance;
        try {
            instance = Cipher.getInstance(RSA_CHIPER);
            instance.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] bytes=instance.doFinal(TobeEncryptMsg.getBytes());
            return new String(Base64.encodeBase64(bytes),ENCODE);
        } catch (Exception e) {
            throw new RuntimeException("RSA加密失败", e);
        }
    }

    /**
     * 解密算法 cryptograph:密文
     */
    public static String rasDecrypt(String cryptograph, PrivateKey privateKey)
            throws Exception {
        /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
        Cipher cipher = Cipher.getInstance(RSA_CHIPER);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] b1 = Base64.decodeBase64(cryptograph.getBytes());
        /** 执行解密操作 */
        byte[] b = cipher.doFinal(b1);
        return new String(b);
    }
}

